import tkinter as tk
from tkinter import ttk, filedialog, scrolledtext
from tkhtmlview import HTMLLabel
from utils.Logger import Logger

from services.AIServiceFactory import AIServiceFactory
from ui.SettingsWindow import SettingsWindow

class MainWindow:
    def __init__(self, root, ai_service, config):
        """主窗口初始化"""
        self.root = root
        self.logger = Logger(__name__)
        self.config = config
        self.ai_service = ai_service
        self.settings_window = SettingsWindow(config)
        
        try:
            self.logger.info("Initializing MainWindow")
            self.setup_ui()
            self.logger.info("MainWindow initialized successfully")
        except Exception as e:
            self.logger.critical(f"Failed to initialize MainWindow: {str(e)}", exc_info=True)
            raise
    
    def setup_ui(self):
        """设置主界面布局"""
        self.logger.debug("Setting up UI components")
        
        # 主窗口配置
        self.root.title("Markdown编辑器")
        self.root.geometry("1000x800")
        
        # 创建主框架
        main_frame = ttk.Frame(self.root)
        main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        # 编辑器区域
        self.editor = scrolledtext.ScrolledText(
            main_frame,
            wrap=tk.WORD,
            font=("Consolas", 12),
            undo=True,  # 启用撤销/重做功能
            maxundo=50  # 设置最大撤销次数
        )
        self.editor.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        self.logger.debug("Editor component initialized")
        
        # 预览区域
        self.preview = HTMLLabel(main_frame)
        self.preview.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)
        self.logger.debug("Preview component initialized")
        
        # 创建菜单栏
        menubar = tk.Menu(self.root)
        self.root.config(menu=menubar)
        
        # 文件菜单
        file_menu = tk.Menu(menubar, tearoff=0)
        file_menu.add_command(label="打开", command=self.open_file)
        file_menu.add_command(label="保存", command=self.save_file)
        menubar.add_cascade(label="文件", menu=file_menu)
        
        # 编辑菜单
        edit_menu = tk.Menu(menubar, tearoff=0)
        edit_menu.add_command(label="撤销", command=lambda: self.editor.event_generate("<<Undo>>"))
        edit_menu.add_command(label="重做", command=lambda: self.editor.event_generate("<<Redo>>"))
        edit_menu.add_separator()
        edit_menu.add_command(label="剪切", command=lambda: self.editor.event_generate("<<Cut>>"))
        edit_menu.add_command(label="复制", command=lambda: self.editor.event_generate("<<Copy>>"))
        edit_menu.add_command(label="粘贴", command=lambda: self.editor.event_generate("<<Paste>>"))
        edit_menu.add_separator()
        edit_menu.add_command(label="全选", command=lambda: self.editor.tag_add("sel", "1.0", "end"))
        menubar.add_cascade(label="编辑", menu=edit_menu)
        
        # AI功能菜单
        ai_menu = tk.Menu(menubar, tearoff=0)
        ai_menu.add_command(label="续写", command=self.continue_writing)
        ai_menu.add_command(label="提问", command=self.ask_question)
        ai_menu.add_command(label="扩写", command=self.expand_text)
        ai_menu.add_command(label="文本摘要", command=self.summarize_text)
        ai_menu.add_command(label="文本翻译", command=self.translate_text)
        ai_menu.add_command(label="风格转换", command=self.convert_style)
        ai_menu.add_command(label="分析代码", command=self.analyze_code)
        menubar.add_cascade(label="AI功能", menu=ai_menu)
        
        # 设置菜单
        settings_menu = tk.Menu(menubar, tearoff=0)
        settings_menu.add_command(label="设置", command=self.show_settings)
        menubar.add_cascade(label="设置", menu=settings_menu)
        
        # 绑定编辑器内容变化事件
        self.editor.bind("<KeyRelease>", self.on_editor_change)
        
        # 绑定快捷键
        # 文件操作快捷键
        self.root.bind("<Control-o>", lambda e: self.open_file())  # Ctrl+O 打开文件
        self.root.bind("<Control-s>", lambda e: self.save_file())  # Ctrl+S 保存文件
        
        # 编辑操作快捷键
        self.root.bind("<Control-z>", lambda e: self.editor.event_generate("<<Undo>>"))  # Ctrl+Z 撤销
        self.root.bind("<Control-y>", lambda e: self.editor.event_generate("<<Redo>>"))  # Ctrl+Y 重做
        self.root.bind("<Control-x>", lambda e: self.editor.event_generate("<<Cut>>"))   # Ctrl+X 剪切
        self.root.bind("<Control-c>", lambda e: self.editor.event_generate("<<Copy>>"))  # Ctrl+C 复制
        self.root.bind("<Control-v>", lambda e: self.editor.event_generate("<<Paste>>")) # Ctrl+V 粘贴
        self.root.bind("<Control-a>", lambda e: self.editor.tag_add("sel", "1.0", "end")) # Ctrl+A 全选
        
        # AI功能快捷键
        self.root.bind("<Control-q>", lambda e: self.ask_question())      # Ctrl+Q 提问
        self.root.bind("<Control-t>", lambda e: self.translate_text())    # Ctrl+T 翻译
        self.root.bind("<Control-e>", lambda e: self.expand_text())       # Ctrl+E 扩写
        self.root.bind("<Control-r>", lambda e: self.continue_writing())  # Ctrl+R 续写
        self.root.bind("<Control-m>", lambda e: self.summarize_text())    # Ctrl+M 摘要
        self.root.bind("<Control-b>", lambda e: self.convert_style())     # Ctrl+B 风格转换
        
        # 更新菜单显示快捷键提示
        # 文件菜单
        file_menu.entryconfig("打开", accelerator="Ctrl+O")
        file_menu.entryconfig("保存", accelerator="Ctrl+S")
        
        # 编辑菜单
        edit_menu.entryconfig("撤销", accelerator="Ctrl+Z")
        edit_menu.entryconfig("重做", accelerator="Ctrl+Y")
        edit_menu.entryconfig("剪切", accelerator="Ctrl+X")
        edit_menu.entryconfig("复制", accelerator="Ctrl+C")
        edit_menu.entryconfig("粘贴", accelerator="Ctrl+V")
        edit_menu.entryconfig("全选", accelerator="Ctrl+A")
        
        # AI功能菜单
        ai_menu.entryconfig("续写", accelerator="Ctrl+R")
        ai_menu.entryconfig("提问", accelerator="Ctrl+Q")
        ai_menu.entryconfig("扩写", accelerator="Ctrl+E")
        ai_menu.entryconfig("文本摘要", accelerator="Ctrl+M")
        ai_menu.entryconfig("文本翻译", accelerator="Ctrl+T")
        ai_menu.entryconfig("风格转换", accelerator="Ctrl+B")
        
        self.logger.debug("UI setup completed")
    
    def open_file(self):
        """打开文件"""
        self.logger.info("Opening file dialog")
        file_path = filedialog.askopenfilename(
            filetypes=[("Markdown文件", "*.md"), ("文本文件", "*.txt"), ("所有文件", "*.*")]
        )
        
        if file_path:
            try:
                self.logger.debug(f"Attempting to open file: {file_path}")
                with open(file_path, "r", encoding="utf-8") as f:
                    content = f.read()
                    self.editor.delete(1.0, tk.END)
                    self.editor.insert(tk.END, content)
                    self.refresh_preview()
                    self.logger.info(f"Successfully opened file: {file_path}")
            except Exception as e:
                self.logger.error(f"Failed to open file {file_path}: {str(e)}", exc_info=True)
                raise
    
    def save_file(self):
        """保存文件"""
        self.logger.info("Opening save file dialog")
        file_path = filedialog.asksaveasfilename(
            defaultextension=".md",
            filetypes=[("Markdown文件", "*.md"), ("文本文件", "*.txt"), ("所有文件", "*.*")]
        )
        
        if file_path:
            try:
                self.logger.debug(f"Attempting to save file: {file_path}")
                with open(file_path, "w", encoding="utf-8") as f:
                    content = self.editor.get(1.0, tk.END)
                    f.write(content)
                    self.logger.info(f"Successfully saved file: {file_path}")
            except Exception as e:
                self.logger.error(f"Failed to save file {file_path}: {str(e)}", exc_info=True)
                raise
    
    def refresh_preview(self):
        """刷新预览"""
        self.logger.debug("Refreshing preview")
        try:
            markdown = self.editor.get(1.0, tk.END)
            preview = self.get_preview(markdown)
            self.preview.set_html(preview)
            self.logger.debug("Preview refreshed successfully")
        except Exception as e:
            self.logger.error(f"Failed to refresh preview: {str(e)}", exc_info=True)
    
    def on_editor_change(self, event=None):
        """编辑器内容变化时自动刷新预览"""
        self.logger.debug("Editor content changed")
        self.refresh_preview()
    
    def get_preview(self, markdown: str) -> str:
        """获取预览"""
        try:
            self.logger.debug("Generating preview")
            import markdown2
            # 使用markdown2将Markdown转换为HTML
            html = markdown2.markdown(
                markdown,
                extras=["fenced-code-blocks", "tables", "code-friendly"]
            )
            return html
        except Exception as e:
            self.logger.error(f"Failed to generate preview: {str(e)}", exc_info=True)
            return f"<pre>{markdown}</pre>"  # 出错时返回原始内容
    
    def continue_writing(self):
        """续写文本"""
        self.logger.info("Initiating text continuation")
        try:
            text = self.editor.get(tk.SEL_FIRST, tk.SEL_LAST)
        except tk.TclError:
            self.logger.warning("No text selected for continuation")

            return
        
        def callback(future):
            try:
                continuation = future.result()
                if continuation:
                    self.editor.replace(tk.SEL_FIRST, tk.SEL_LAST, continuation)
                    self.logger.info("Text continuation completed successfully")
            except Exception as e:
                self.logger.error(f"Failed to continue text: {str(e)}", exc_info=True)
        
        import asyncio
        future = asyncio.run_coroutine_threadsafe(
            self.ai_service.continue_writing(text),
            asyncio.get_event_loop()
        )
        future.add_done_callback(callback)
    
    def ask_question(self):
        """提问"""
        self.logger.info("Initiating question answering")
        try:
            question = self.editor.get(tk.SEL_FIRST, tk.SEL_LAST)
        except tk.TclError:
            self.logger.warning("No text selected for question")
            return
        
        def callback(future):
            try:
                answer = future.result()
                if answer:
                    self.show_analysis_result(answer)
                    self.logger.info("Question answered successfully")
            except Exception as e:
                self.logger.error(f"Failed to answer question: {str(e)}", exc_info=True)
        
        import asyncio
        future = asyncio.run_coroutine_threadsafe(
            self.ai_service.ask_question(question),
            asyncio.get_event_loop()
        )
        future.add_done_callback(callback)
    
    def expand_text(self):
        """扩写文本"""
        self.logger.info("Initiating text expansion")
        try:
            text = self.editor.get(tk.SEL_FIRST, tk.SEL_LAST)
        except tk.TclError:
            self.logger.warning("No text selected for expansion")
            return
        
        def callback(future):
            try:
                expanded = future.result()
                if expanded:
                    self.editor.replace(tk.SEL_FIRST, tk.SEL_LAST, expanded)
                    self.logger.info("Text expanded successfully")
            except Exception as e:
                self.logger.error(f"Failed to expand text: {str(e)}", exc_info=True)
        
        import asyncio
        future = asyncio.run_coroutine_threadsafe(
            self.ai_service.expand_text(text),
            asyncio.get_event_loop()
        )
        future.add_done_callback(callback)
    
    def analyze_code(self):
        """分析代码"""
        self.logger.info("Initiating code analysis")
        try:
            code = self.editor.get(tk.SEL_FIRST, tk.SEL_LAST)
        except tk.TclError:
            self.logger.warning("No text selected for code analysis")
            return
        
        def callback(future):
            try:
                analysis = future.result()
                if analysis:
                    self.show_analysis_result(analysis)
                    self.logger.info("Code analysis completed successfully")
            except Exception as e:
                self.logger.error(f"Failed to analyze code: {str(e)}", exc_info=True)
        
        import asyncio
        future = asyncio.run_coroutine_threadsafe(
            self.ai_service.analyze_code(code),
            asyncio.get_event_loop()
        )
        future.add_done_callback(callback)
    
    def show_analysis_result(self, analysis):
        """显示分析结果"""
        self.logger.info("Showing analysis result")
        try:
            result_window = tk.Toplevel(self.root)
            result_window.title("代码分析结果")
            result_text = scrolledtext.ScrolledText(result_window, wrap=tk.WORD)
            result_text.pack(fill=tk.BOTH, expand=True)
            result_text.insert(tk.END, str(analysis))
            self.logger.debug("Analysis result window shown")
        except Exception as e:
            self.logger.error(f"Failed to show analysis result: {str(e)}", exc_info=True)
    
    def show_settings(self):
        """显示设置窗口"""
        self.logger.info("Showing settings window")
        try:
            # 先显示设置窗口
            self.settings_window.show(self.root)
            
            # 设置窗口关闭后执行回调
            if self.settings_window.window.winfo_exists():
                def on_window_close():
                    if hasattr(self.settings_window, 'window'):
                        self.settings_window.window.destroy()
                        self._on_settings_saved()  # 窗口关闭后执行回调
                    
                self.settings_window.window.protocol("WM_DELETE_WINDOW", on_window_close)
                
            self.logger.info("Settings window shown successfully")
        except Exception as e:
            self.logger.error(f"Failed to show settings window: {str(e)}", exc_info=True)

    def summarize_text(self):
        self.logger.info("Initiating text summarization")
        try:
            text = self.editor.get(tk.SEL_FIRST, tk.SEL_LAST)
        except tk.TclError:
            self.logger.warning("No text selected for summarization")
            return

        def callback(future):
            try:
                summary = future.result()
                if summary:
                    self.show_analysis_result(summary)
                    self.logger.info("Text summarization completed successfully")
            except Exception as e:
                self.logger.error(f"Failed to summarize text: {str(e)}", exc_info=True)

        import asyncio
        future = asyncio.run_coroutine_threadsafe(
            self.ai_service.summarize_text(text),
            asyncio.get_event_loop()
        )
        future.add_done_callback(callback)

    def translate_text(self):
        self.logger.info("Initiating text translation")
        try:
            text = self.editor.get(tk.SEL_FIRST, tk.SEL_LAST)
        except tk.TclError:
            self.logger.warning("No text selected for translation")
            return

        # 创建翻译选项窗口
        translation_window = tk.Toplevel(self.root)
        translation_window.title("翻译选项")
        
        # 目标语言选择
        ttk.Label(translation_window, text="目标语言:").grid(row=0, column=0, padx=5, pady=5)
        self.target_language_var = tk.StringVar(value="英语 (English)")
        language_options = {
            "en": "英语 (English)",
            "zh": "中文 (Chinese)",
            "ja": "日语 (Japanese)",
            "fr": "法语 (French)",
            "de": "德语 (German)",
            "es": "西班牙语 (Spanish)"
        }
        language_combobox = ttk.Combobox(translation_window,
                                        textvariable=self.target_language_var,
                                        values=list(language_options.values()),
                                        state="readonly")
        language_combobox.grid(row=0, column=1, padx=5, pady=5)

        # 确认按钮
        def start_translation():
            translation_window.destroy()
            selected_language = self.target_language_var.get()
            # 从显示文本转换回语言代码
            target_language = {v: k for k, v in language_options.items()}[selected_language]

            def callback(future):
                try:
                    translation = future.result()
                    if translation:
                        self.show_analysis_result(translation)
                        self.logger.info("Text translation completed successfully")
                except Exception as e:
                    self.logger.error(f"Failed to translate text: {str(e)}", exc_info=True)

            import asyncio
            future = asyncio.run_coroutine_threadsafe(
                self.ai_service.translate_text(text, target_language),
                asyncio.get_event_loop()
            )
            future.add_done_callback(callback)

        ttk.Button(translation_window, text="开始翻译", command=start_translation).grid(row=1, column=0, columnspan=2, pady=10)

    def convert_style(self):
        self.logger.info("Initiating style conversion")
        try:
            text = self.editor.get(tk.SEL_FIRST, tk.SEL_LAST)
        except tk.TclError:
            self.logger.warning("No text selected for style conversion")
            return

        # 创建风格选择窗口
        style_window = tk.Toplevel(self.root)
        style_window.title("风格转换选项")
        
        # 目标风格选择
        ttk.Label(style_window, text="目标风格:").grid(row=0, column=0, padx=5, pady=5)
        self.target_style_var = tk.StringVar(value="正式风格")
        style_options = {
            "formal": "正式风格",
            "casual": "日常口语",
            "professional": "专业技术",
            "literary": "文学风格",
            "business": "商务风格"
        }
        
        style_combobox = ttk.Combobox(style_window,
                                    textvariable=self.target_style_var,
                                    values=list(style_options.values()),
                                    state="readonly")
        style_combobox.grid(row=0, column=1, padx=5, pady=5)

        # 确认按钮
        def start_conversion():
            style_window.destroy()
            selected_style = self.target_style_var.get()
            # 从显示文本转换回风格代码
            target_style = {v: k for k, v in style_options.items()}[selected_style]

            def callback(future):
                try:
                    converted = future.result()
                    if converted:
                        self.editor.replace(tk.SEL_FIRST, tk.SEL_LAST, converted)
                        self.logger.info("Style conversion completed successfully")
                except Exception as e:
                    self.logger.error(f"Failed to convert style: {str(e)}", exc_info=True)

            import asyncio
            future = asyncio.run_coroutine_threadsafe(
                self.ai_service.convert_style(text, target_style),
                asyncio.get_event_loop()
            )
            future.add_done_callback(callback)

        ttk.Button(style_window, text="开始转换", command=start_conversion).grid(row=1, column=0, columnspan=2, pady=10)

    def _on_settings_saved(self):
        """设置保存后的回调函数"""
        try:
            # 重新创建 AI 服务实例
            provider = self.config.get_current_provider()
            api_key = self.config.get_api_key(provider)
            self.ai_service = AIServiceFactory.create_service(self.config)
            self.logger.info(f"AI service recreated after settings update: {provider}")
        except Exception as e:
            self.logger.error(f"Failed to recreate AI service: {str(e)}")
